package com.example.brushtesting;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposePathEffect;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.DiscretePathEffect;
import android.graphics.EmbossMaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.PathDashPathEffect.Style;
import android.graphics.PathEffect;
import android.graphics.SumPathEffect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class LineDrawingView extends View {

	public static final int EFFECT_NONE = 0;
	public static final int EFFECT_BLUR = 1;
	public static final int EFFECT_EMBOSS = 2;
	public static final int EFFECT_SHADOW = 3;
	public static final int EFFECT_DASH = 4;
	public static final int EFFECT_ComposePathEffect = 5; 
	public static final int EFFECT_CornerPathEffect = 6;
	public static final int EFFECT_DiscretePathEffect = 7;
	public static final int EFFECT_PathDashPathEffect = 8;
	public static final int EFFECT_SumPathEffect = 9;

	private Paint mPaint;
	private Path    mPath;
	private Shapes mShapes;
	private ArrayList<Shapes> mShapesArray = new ArrayList<Shapes>();
	private int mLineWidth;
	private int mEffect;
	private int mBackgroundColour;
	private int mLineColour;
	private Paint.Style mStyle = Paint.Style.STROKE;
	private Paint.Join mStrokeJoin = Paint.Join.ROUND;
	private Paint.Cap mStrokeCap = Paint.Cap.ROUND;
	private float mRadius = 0;
	private BlurMaskFilter.Blur mBlurStyle = BlurMaskFilter.Blur.NORMAL;

	private float mX, mY;
	private static final float TOUCH_TOLERANCE = 4;

	private Bitmap  mBitmap;        
	private Paint   mBitmapPaint;

	public LineDrawingView(Context context) {
		this(context, null, 0);
	}
	public LineDrawingView(Context context, AttributeSet attributeSet)
	{
		this(context,attributeSet,0);
	}

	public LineDrawingView(Context context, AttributeSet attrs, int defStyle) {

		super(context, attrs, defStyle);

		setBackgroundColour(Color.WHITE);
		setLineColour(Color.RED);
		setLineWidth(6);
		setEffect(EFFECT_NONE);
		setStyle(Paint.Style.STROKE);
		setStrokeCap(Paint.Cap.ROUND);
		setStrokeJoin(Paint.Join.ROUND);
		setRadius(8);

		setPaint();

		mPath = new Path();
		mBitmapPaint = new Paint(Paint.DITHER_FLAG);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		onClickNew(null);            
	}

	@Override
	protected void onDraw(Canvas canvas) {

		canvas.drawColor(getBackgroundColour());
		canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

		for (Shapes shapes : mShapesArray){
			canvas.drawPath(shapes.getPath(), shapes.getPaint());
		}
		canvas.drawPath(mPath, mPaint);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		float x = (int)event.getX();
		float y = (int)event.getY();

		switch (event.getAction()){
		case MotionEvent.ACTION_DOWN:
			touch_start(x,y);
			break;
		case MotionEvent.ACTION_UP:
			touch_up();
			break;
		case MotionEvent.ACTION_MOVE:
			touch_move(x,y);
			break;
		}
		invalidate();
		return true;
	}

	private void touch_start(float x, float y) {
		mPath.reset();
		mPath.moveTo(x, y);
		mX = x;
		mY = y;
	}
	private void touch_move(float x, float y) {
		float dx = Math.abs(x - mX);
		float dy = Math.abs(y - mY);
		if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
			mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
			mX = x;
			mY = y;
		}
	}
	private void touch_up() {
		mPath.lineTo(mX, mY);
		mShapes = new Shapes(mPath, mPaint);
		mShapesArray.add(mShapes);
		mPath = new Path();
		setPaint();
	}

	public void setPaint(){
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		mPaint.setStyle(getStyle());
		mPaint.setStrokeJoin(getStrokeJoin());
		mPaint.setStrokeCap(getStrokeCap());
		mPaint.setColor(getLineColour());
		mPaint.setStrokeWidth(getLineWidth());

		switch(getEffect()){
		case EFFECT_BLUR:
			BlurMaskFilter blur = new BlurMaskFilter(getRadius(), getBlurStyle());
			mPaint.setMaskFilter(blur);
			break;
		case EFFECT_EMBOSS:
			EmbossMaskFilter emboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
			//EmbossMaskFilter emboss1 = new EmbossMaskFilter(direction, ambient, specular, blurRadius);
			mPaint.setMaskFilter(emboss);
			break;
		case EFFECT_DASH:
			DashPathEffect dash = new DashPathEffect(new float[] { 8, 8 }, 0);
			//DashPathEffect dash = new DashPathEffect(intervals, phase);
			mPaint.setPathEffect(dash);
			break;
		case EFFECT_ComposePathEffect:
			PathEffect outerpe = new DiscretePathEffect(6, 4);
			PathEffect innerpe = new DashPathEffect(new float[] { 8, 8,4,4,2,8 }, 0);
			mPaint.setPathEffect(new ComposePathEffect(outerpe, innerpe));
			break;
		case EFFECT_CornerPathEffect:
			mPaint.setPathEffect(new CornerPathEffect(getRadius()));
			break;
		case EFFECT_DiscretePathEffect:
			float segmentLength = 6;
			float deviation = 4;
			mPaint.setPathEffect(new DiscretePathEffect(segmentLength, deviation));
			break;
		case EFFECT_PathDashPathEffect:
			Path shape = new Path();
			shape.addCircle(10f, 10f, 10f, Path.Direction.CW);
			float advance = 5;
			float phase = 1;
			Style style = Style.MORPH;
			mPaint.setPathEffect(new PathDashPathEffect(shape, advance, phase, style));
			break;
		case EFFECT_SumPathEffect:
			PathEffect second = new DiscretePathEffect(6, 4);
			PathEffect first = new DashPathEffect(new float[] { 8, 8, }, 0);
			mPaint.setPathEffect(new SumPathEffect(first, second)); 
			break;

		case EFFECT_SHADOW:
			mPaint.setShadowLayer(getRadius(), 0, 2, Color.GREEN);
			//mPaint.setShadowLayer(radius, dx, dy, color);
		case EFFECT_NONE:
			break;
		}

		/*
		 * //Initialize the bitmap object by loading an image from the resources folder  
    fillBMP = BitmapFactory.decodeResource(m_context.getResources(), R.drawable.cross);  
    //Initialize the BitmapShader with the Bitmap object and set the texture tile mode  
    fillBMPshader = new BitmapShader(fillBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);  

    fillPaint.setStyle(Paint.Style.FILL);  
    //Assign the 'fillBMPshader' to this paint  
    fillPaint.setShader(fillBMPshader);  

    //Draw the fill of any shape you want, using the paint object.
    canvas.drawCircle(posX, posY, 100, fillPaint);


		 * 
		 *  mPaint.setPathEffect(new DashPathEffect(new float[] { 8, 8 }, 0));
		/*
		 * Other effects
		 * ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect
		 * paint.setShadowLayer(float radius, float dx, float dy, int color)
		 * glowPaint.setMaskFilter(new BlurMaskFilter(20, Blur.NORMAL));
		 * // start at 0,0 and go to 0,max to use a vertical
    // gradient the full height of the screen.
    p.setShader(new LinearGradient(0, 0, 0, getHeight(), Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR));


     int w = getWidth();
    int h = getHeight();
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
    Path pth = new Path();
    pth.moveTo(w*0.27f,0);
    pth.lineTo(w*0.73f,0);
    pth.lineTo(w*0.92f,h);
    pth.lineTo(w*0.08f,h);
    pth.lineTo(w*0.27f,0);
    p.setColor(0xff800000);
    p.setShader(new LinearGradient(0,0,0,h,0xff000000,0xffffffff,Shader.TileMode.CLAMP));
		 */



	}

	public void onClickNew (Bitmap bitmap){
		mShapesArray.clear();
		if(bitmap==null){
			mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
		}else{
			mBitmap = bitmap;	
		}
		invalidate();
	}

	public int getLineWidth() {
		return mLineWidth;
	}

	public void setLineWidth(int lineWidth) {
		this.mLineWidth = lineWidth;
	}

	public int getLineColour() {
		return mLineColour;
	}

	public void setLineColour(int colour) {
		this.mLineColour = colour;
	}

	public int getBackgroundColour() {
		return mBackgroundColour;
	}

	public void setBackgroundColour(int colour) {
		this.mBackgroundColour = colour;
		invalidate();
	}
	public int getEffect() {
		return mEffect;
	}
	public void setEffect(int effect) {
		this.mEffect = effect;
	}
	public Paint.Style getStyle() {
		return mStyle;
	}
	public void setStyle(Paint.Style style) {
		this.mStyle = style;
	}
	public Paint.Join getStrokeJoin() {
		return mStrokeJoin;
	}
	public void setStrokeJoin(Paint.Join strokeJoin) {
		this.mStrokeJoin = strokeJoin;
	}
	public Paint.Cap getStrokeCap() {
		return mStrokeCap;
	}
	public void setStrokeCap(Paint.Cap strokeCap) {
		this.mStrokeCap = strokeCap;
	}
	public float getRadius() {
		return mRadius;
	}
	public void setRadius(float radius) {
		this.mRadius = radius;
	}
	public BlurMaskFilter.Blur getBlurStyle() {
		return mBlurStyle;
	}
	public void setBlurStyle(BlurMaskFilter.Blur blurStyle) {
		this.mBlurStyle = blurStyle;
	}

}
